using System;
using System.Data; 
using System.Data.Odbc;
using System.IO;
using System.Globalization;

namespace Waymex.Gis.Shape
{
	/// <summary>
	/// Summary description for ShapeFile.
	/// </summary>
#if(PUBLIC)
#else
#endif

#if(PUBLIC)
	public class ShapeFile : Waymex.Gis.Shape.ShapeBase
#else
	internal class ShapeFile : Waymex.Gis.Shape.ShapeBase
#endif
	{
		private const string C_MAIN_FILE_EXT = ".shp";
		private const string C_INDEX_FILE_EXT = ".shx";
		private const string C_DATA_FILE_EXT = ".dbf";
 
		private System.Collections.ArrayList m_colShapes; 
		private System.Collections.ArrayList m_colAttributeCollections;

		//bounding box
		private double m_dblXmin = 0.0;			//little endian
		private double m_dblYmin = 0.0;			//little endian
		private double m_dblXmax = 0.0;			//little endian
		private double m_dblYmax = 0.0;			//little endian
		private double m_dblZmin = 0.0;			//little endian, should be zero if not a Z or M type
		private double m_dblZmax = 0.0;			//little endian, should be zero if not a Z or M type
		private double m_dblMmin = 0.0;			//little endian, should be zero if not a Z or M type
		private double m_dblMmax = 0.0;			//little endian, should be zero if not a Z or M type
		
		//shape type, determines what shapes can be added to the file
		//this is set by the first shape passed to the shapefile
		private int m_intShapeType = 0;					//little endian

		//file header properties
		private int m_intFileCode = 9994;		//big endian
		private int m_intUnused1 = 0;			//big endian
		private int m_intUnused2 = 0;			//big endian
		private int m_intUnused3 = 0;			//big endian
		private int m_intUnused4 = 0;			//big endian
		private int m_intUnused5 = 0;			//big endian
		private int m_intFileLength = 0;		//big endian
		private int m_intVersion = 1000;		//little endian

		//example attribute, determines what attribute can be added to the file
		//this is set by the first shape/attribute passed to the shapefile
		private Attributes m_objAttributesDefinition = null;


		public ShapeFile()
		{
			m_colShapes = new System.Collections.ArrayList();
			m_colAttributeCollections = new System.Collections.ArrayList();
		}

        public void Save(string Folder, string Filename)
        {
            //strFilename must be 8 chars or less
            if (Filename.Length > 8)
            {
                throw new System.IO.FileNotFoundException(ERR_MSG_1003);
            }

            //determine if folder exists
            if (!Directory.Exists(Folder))
            {
                Directory.CreateDirectory(Folder);
            }

            if (m_colShapes.Count > 0)
            {
                //create the main file
                CreateBinaryFiles(Folder, Filename);

                //Create the data file
                //TODO: try using the Data Adapter to populate the table
                CreateDataFile(Folder, Filename);
            }
        }

		private void CreateBinaryFiles(string p_strFolder, string p_strFilename)
		{
			//byte arrays for storing the files
			byte[]	bytShapeHeader = null;		//file header for main file
			byte[]	bytShapeRecords = null;		//all shape records
			byte[]	bytShapeFile = null;		//complete shape file (header + records)
			byte[]	bytIndexHeader = null;		//file header for index file
			byte[]  bytIndexRecords = null;		//all index records
			byte[]	bytIndexFile = null;		//complete index file (header + records)

			//these two are for for creating the index file
			int		intOffset = 50; //to allow for the header
			int		intContentLength = 0;

			string strMainFileName = "";
			string strIndexFileName = "";
			string strFullPathMain = "";
			string strFullPathIndex = "";


			try
			{
				//determine individual file names
				strMainFileName = string.Concat(p_strFilename,C_MAIN_FILE_EXT);
				strIndexFileName = string.Concat(p_strFilename,C_INDEX_FILE_EXT);

				//determine full path names
				if(p_strFolder.Substring(p_strFolder.Length - 1,1) == @"\")
				{
					strFullPathMain = p_strFolder + strMainFileName;
					strFullPathIndex = p_strFolder + strIndexFileName;
				}
				else
				{
					strFullPathMain = p_strFolder + @"\" + strMainFileName;
					strFullPathIndex = p_strFolder + @"\" + strIndexFileName;
				}

				//delete any existing main file
				if(File.Exists(strFullPathMain))
				{
					File.Delete(strFullPathMain);
				}
				//delete any existing index file
				if(File.Exists(strFullPathIndex))
				{
					File.Delete(strFullPathIndex);
				}

				//record header
				int		intRecordLength = 0;	//little endian
				int		intRecordCount = 0;		//little endian

				//create the main and index files
				foreach(ShapeBase objShape in m_colShapes)
				{
					//increment the record counter for each record
					intRecordCount++;

					//collect the values for the index array
					if(bytShapeRecords != null)
					{
						//offset is the record length + the length of the record header (4 words)
						intOffset = intOffset + intRecordLength + 4;
					}

                    //determine length in words of each record
					intRecordLength = objShape.ToByte().Length / 2;

					//content length for the index file
					intContentLength = intRecordLength;	//same as the value in the main file Record Header

					//add the record header to the main file
					bytShapeRecords = ByteConcat(bytShapeRecords,ConvertToByte(intRecordCount,ByteOrder.ByteOrderBigEndian));
					bytShapeRecords = ByteConcat(bytShapeRecords,ConvertToByte(intRecordLength,ByteOrder.ByteOrderBigEndian));
				
					//add the shape record to the main file
					bytShapeRecords = ByteConcat(bytShapeRecords,objShape.ToByte());

					//add the index entry to the index file
					bytIndexRecords = ByteConcat(bytIndexRecords,ConvertToByte(intOffset,ByteOrder.ByteOrderBigEndian));
					bytIndexRecords = ByteConcat(bytIndexRecords,ConvertToByte(intContentLength,ByteOrder.ByteOrderBigEndian));
				}

				//once we have the shape records then we can create the file header for the main file

				//determine the file length this is the length of the shape
				//records in words plus the 50 word file header
				m_intFileLength = (bytShapeRecords.Length / 2) + 50;

				bytShapeHeader = ByteConcat(bytShapeHeader,ConvertToByte(m_intFileCode, ByteOrder.ByteOrderBigEndian));
				bytShapeHeader = ByteConcat(bytShapeHeader,ConvertToByte(m_intUnused1, ByteOrder.ByteOrderBigEndian));
				bytShapeHeader = ByteConcat(bytShapeHeader,ConvertToByte(m_intUnused2, ByteOrder.ByteOrderBigEndian));
				bytShapeHeader = ByteConcat(bytShapeHeader,ConvertToByte(m_intUnused3, ByteOrder.ByteOrderBigEndian));
				bytShapeHeader = ByteConcat(bytShapeHeader,ConvertToByte(m_intUnused4, ByteOrder.ByteOrderBigEndian));
				bytShapeHeader = ByteConcat(bytShapeHeader,ConvertToByte(m_intUnused5, ByteOrder.ByteOrderBigEndian));
				bytShapeHeader = ByteConcat(bytShapeHeader,ConvertToByte(m_intFileLength, ByteOrder.ByteOrderBigEndian));
				bytShapeHeader = ByteConcat(bytShapeHeader,ConvertToByte(m_intVersion, ByteOrder.ByteOrderLittleEndian));
				bytShapeHeader = ByteConcat(bytShapeHeader,ConvertToByte(m_intShapeType, ByteOrder.ByteOrderLittleEndian));
				bytShapeHeader = ByteConcat(bytShapeHeader,ConvertToByte(m_dblXmin, ByteOrder.ByteOrderLittleEndian));
				bytShapeHeader = ByteConcat(bytShapeHeader,ConvertToByte(m_dblYmin, ByteOrder.ByteOrderLittleEndian));
				bytShapeHeader = ByteConcat(bytShapeHeader,ConvertToByte(m_dblXmax, ByteOrder.ByteOrderLittleEndian));
				bytShapeHeader = ByteConcat(bytShapeHeader,ConvertToByte(m_dblYmax, ByteOrder.ByteOrderLittleEndian));
				bytShapeHeader = ByteConcat(bytShapeHeader,ConvertToByte(m_dblZmin, ByteOrder.ByteOrderLittleEndian));
				bytShapeHeader = ByteConcat(bytShapeHeader,ConvertToByte(m_dblZmax, ByteOrder.ByteOrderLittleEndian));
				bytShapeHeader = ByteConcat(bytShapeHeader,ConvertToByte(m_dblMmin, ByteOrder.ByteOrderLittleEndian));
				bytShapeHeader = ByteConcat(bytShapeHeader,ConvertToByte(m_dblMmax, ByteOrder.ByteOrderLittleEndian));

				//now we add the shaperecords to the fileheader, this is then
				//the full shape file in byte format and should be written to disk
				bytShapeFile = ByteConcat(bytShapeHeader, bytShapeRecords);

				//removed as it causes severe delays with tracklogs
				//Debug.WriteLine("Shape Header  = " + ByteToHex(bytShapeHeader));
				//Debug.WriteLine("Shape Records = " + ByteToHex(bytShapeRecords));

				//write the main file bytes to disk
				Stream MainStream = File.OpenWrite(strFullPathMain);
				MainStream.Write(bytShapeFile,0,bytShapeFile.Length);
				MainStream.Close();


				//now create the index header
				//determine the file length this is the length of the shape
				//records in words plus the 50 word file header
				m_intFileLength = bytIndexRecords.Length / 2 + 50;

				bytIndexHeader = ByteConcat(bytIndexHeader,ConvertToByte(m_intFileCode, ByteOrder.ByteOrderBigEndian));
				bytIndexHeader = ByteConcat(bytIndexHeader,ConvertToByte(m_intUnused1, ByteOrder.ByteOrderBigEndian));
				bytIndexHeader = ByteConcat(bytIndexHeader,ConvertToByte(m_intUnused2, ByteOrder.ByteOrderBigEndian));
				bytIndexHeader = ByteConcat(bytIndexHeader,ConvertToByte(m_intUnused3, ByteOrder.ByteOrderBigEndian));
				bytIndexHeader = ByteConcat(bytIndexHeader,ConvertToByte(m_intUnused4, ByteOrder.ByteOrderBigEndian));
				bytIndexHeader = ByteConcat(bytIndexHeader,ConvertToByte(m_intUnused5, ByteOrder.ByteOrderBigEndian));
				bytIndexHeader = ByteConcat(bytIndexHeader,ConvertToByte(m_intFileLength, ByteOrder.ByteOrderBigEndian));
				bytIndexHeader = ByteConcat(bytIndexHeader,ConvertToByte(m_intVersion, ByteOrder.ByteOrderLittleEndian));
				bytIndexHeader = ByteConcat(bytIndexHeader,ConvertToByte(m_intShapeType, ByteOrder.ByteOrderLittleEndian));
				bytIndexHeader = ByteConcat(bytIndexHeader,ConvertToByte(m_dblXmin, ByteOrder.ByteOrderLittleEndian));
				bytIndexHeader = ByteConcat(bytIndexHeader,ConvertToByte(m_dblYmin, ByteOrder.ByteOrderLittleEndian));
				bytIndexHeader = ByteConcat(bytIndexHeader,ConvertToByte(m_dblXmax, ByteOrder.ByteOrderLittleEndian));
				bytIndexHeader = ByteConcat(bytIndexHeader,ConvertToByte(m_dblYmax, ByteOrder.ByteOrderLittleEndian));
				bytIndexHeader = ByteConcat(bytIndexHeader,ConvertToByte(m_dblZmin, ByteOrder.ByteOrderLittleEndian));
				bytIndexHeader = ByteConcat(bytIndexHeader,ConvertToByte(m_dblZmax, ByteOrder.ByteOrderLittleEndian));
				bytIndexHeader = ByteConcat(bytIndexHeader,ConvertToByte(m_dblMmin, ByteOrder.ByteOrderLittleEndian));
				bytIndexHeader = ByteConcat(bytIndexHeader,ConvertToByte(m_dblMmax, ByteOrder.ByteOrderLittleEndian));

				//now we add the shaperecords to the fileheader, this is then
				//the full shape file in byte format and should be written to disk
				bytIndexFile = ByteConcat(bytIndexHeader, bytIndexRecords);

				//removed as it causes severe delays with tracklogs
				//Debug.WriteLine("Index Header  = " + ByteToHex(bytIndexHeader));
				//Debug.WriteLine("Index Records = " + ByteToHex(bytIndexRecords));

				//write the main file bytes to disk
				Stream IndexStream = File.OpenWrite(strFullPathIndex);
				IndexStream.Write(bytIndexFile,0,bytIndexFile.Length);
				IndexStream.Close();

			}
			catch(Exception e)
			{
				throw e;
			}
		}
		
		private void CreateDataFile(string p_strFolder, string p_strFilename)
		{
			//syntax stuff

			//CREATE TABLE | DBF TableName1 [NAME LongTableName] [FREE]
			//   (FieldName1 FieldType [(nFieldWidth [, nPrecision])]
			//      [NULL | NOT NULL] 
			//      [CHECK lExpression1 [ERROR cMessageText1]]
			//      [DEFAULT eExpression1]
			//      [PRIMARY KEY | UNIQUE]
			//      [REFERENCES TableName2 [TAG TagName1]]
			//      [NOCPTRANS]
			//   [, FieldName2 ...]
			//      [, PRIMARY KEY eExpression2 TAG TagName2
			//      |, UNIQUE eExpression3 TAG TagName3]
			//      [, FOREIGN KEY eExpression4 TAG TagName4 [NODUP]
			//            REFERENCES TableName3 [TAG TagName5]]
			//      [, CHECK lExpression2 [ERROR cMessageText2]])
			//| FROM ARRAY ArrayName

			//INSERT INTO strDatabase (LONGTITUDE,LATTITUDE) VALUES(21,23)
			
			string strDatabase = "";
			string strConnectString = "";
			string strSQL = "";
			string strType = "";
			string strValue = "";
			string strDataFileName = "";
			string strFolder = "";


			try

			{
				//determine the filename
				strDataFileName = string.Concat(p_strFilename, C_DATA_FILE_EXT);

				//determine folder name
				if(p_strFolder.Substring(p_strFolder.Length - 1,1) != @"\")
				{
					strFolder = string.Concat(p_strFolder, @"\");
				}
				else
				{
					strFolder = p_strFolder;
				}

				//the working directory to the folder name
				Directory.SetCurrentDirectory(strFolder);

				//delete any existing file
				if(File.Exists(strDataFileName))
				{
					File.Delete(strDataFileName);
				}

				//set the database
				//TODO: try this with the database set to the filename only and change

				strDatabase = strDataFileName;

				//determine connection string
				strConnectString = string.Concat(@"DRIVER={Microsoft dBase Driver (*.dbf)};DBQ=", strFolder,  @";DefaultDir=", strFolder, @";DriverId=533;MaxBufferSize=2048;PageTimeout=5"); 
			
				//build up the create table SQL
				strSQL = string.Concat("CREATE TABLE ", strDataFileName, " (");
			
				//for each attribute add a line as below
				foreach(Attribute objAttr in m_objAttributesDefinition)
				{
					if(objAttr.Type == Attribute.DataType.String)
					{
						strType = "text";
					}
					else
					{
						strType = "numeric";
					}

					//strSelectString = string.Concat(strSelectString,"Longitude numeric",",");
					//strSelectString = string.Concat(strSelectString,"Latitude numeric",",");
					strSQL = string.Concat(strSQL, objAttr.Name," ",strType,",");
				}

				//if we have finished remove the last comma and add the closing brace
				strSQL = strSQL.Substring(0,strSQL.Length - 1);
				strSQL = string.Concat(strSQL,")");

				using (OdbcConnection myCon = new OdbcConnection(strConnectString) ) 
				{ 
					if (myCon.State != ConnectionState.Open) //if connection is not open, open it 
						myCon.Open(); 

					//Debug.WriteLine("Open database successfully!");

					OdbcCommand myCmd = new OdbcCommand(strSQL , myCon); 
					myCmd.ExecuteNonQuery();

					//add attributes to the table
					foreach(Attributes objAttributes in m_colAttributeCollections)
					{
						strSQL = string.Concat("INSERT INTO ", strDatabase, " (");
						//add the field names
						foreach(Attribute objAttribute in objAttributes)
						{
							strSQL = string.Concat(strSQL,objAttribute.Name,",");
						}
						//remove trailing comma
						strSQL = strSQL.Substring(0,strSQL.Length - 1);
					
						//add the closing and opening braces
						strSQL = string.Concat(strSQL,") VALUES(");

						//add the field values
						foreach(Attribute objAttribute in objAttributes)
						{
							if(objAttribute.Type == Attribute.DataType.String)
							{
								strValue = string.Concat("'",objAttribute.ToString(),"'");
							}
							else
							{
								strValue = objAttribute.ToString();
							}

							strSQL = string.Concat(strSQL,strValue,",");
						}

						//remove trailing comma
						strSQL = strSQL.Substring(0,strSQL.Length - 1);
						//add the closing and opening braces
						strSQL = string.Concat(strSQL,")");

						//strSQL = "INSERT INTO wpt1.dbf (NMBR,Y,X,COMMENT,SYMBOL,COLOUR,DISPLAY,PROX_DIST,PROX_INDEX,ALTITUDE,DEPTH,CLASS,ATTRIBUTES,LINK,STATE,COUNTRY,CITY,ADDRESS,FACILITY,ROAD,PKT_TYPE,TIME_ENRTE) VALUES('0',6046767.29203569,489002.445934809,'',0,31,0,1E+25,0,-0.1143799,-0.006509781,0,112,'','','','','','','',1,-1)";
						myCmd = new OdbcCommand(strSQL , myCon); 
						myCmd.ExecuteNonQuery();

					}				

					myCon.Close();
				}
			}
			catch(Exception e)
			{
				throw new ShapeException(e.Message, e); 
			}
		}
		


		//		private bool CreateDataFile2(string strFolder, string strFilename)
		//		{
		//			string strDatabase = "";
		//			string strConnectString = "";
		//			string strSQL = "";
		//			string strType = "";
		//			string strValue = "";
		//			
		//			try
		//			{
		//				strDatabase = string.Concat(strFolder,"\\",strFilename);
		//				strConnectString = string.Concat(@"DRIVER={Microsoft dBase Driver (*.dbf)};DBQ=", strFolder,  @";DefaultDir=", strFolder, @";DriverId=533;MaxBufferSize=2048;PageTimeout=5"); 
		//
		//				//create the connection object
		//				OdbcConnection objConn = new OdbcConnection(strConnectString); 
		//					
		//				//create the empty dataset
		//				DataSet objDataSet = new DataSet();
		//					
		//				//create a new datatable
		//				DataTable objDataTable = new DataTable("2");
		//		
		//				//create the columns
		//				DataColumn objLongitude = new DataColumn("Longitude");
		//				objLongitude.DataType = typeof(double);
		//		
		//				DataColumn objLatitude = new DataColumn("Latitude");
		//				objLatitude.DataType = typeof(double);
		//		
		//				//add columns to the table
		//				objDataTable.Columns.Add(objLongitude);
		//				objDataTable.Columns.Add(objLatitude);
		//		
		//				//add the table to the dataset
		//				objDataSet.Tables.Add(objDataTable);
		//		
		//				//add some data
		//				DataRow objRow = objDataTable.NewRow();
		//				objRow["Longitude"] = -2.0;
		//				objRow["Latitude"] = 54.00;
		//				objDataTable.Rows.Add(objRow);
		//		
		//				//update the table
		//				OdbcDataAdapter objDA = new OdbcDataAdapter("SELECT * FROM 2",objConn);
		//				objDA.Update(objDataSet);
		//		
		//
		//			}
		//			catch(Exception e)
		//			{
		//				throw new Exceptions.GISShapeException(e.Message, e); 
		//			}
		//
		//			return true;
		//		
		//		}

		public void AppendShape(Waymex.Gis.Shape.ShapeBase Shape, Attributes Attributes)
		{
			try
			{
				//need to check that any shape added is either a null or the
				//same as a previous shape.
				if(m_colShapes.Count > 0)
				{
					//not the first shape so check what the new shape is
					if(!((int)Shape.Type == m_intShapeType || Shape.Type == ShapeBase.ShapeType.ShapeTypeNull))
					{
						throw new ShapeTypeException(ERR_MSG_1001);
					}

					if(!CompareAttributes(m_objAttributesDefinition, Attributes))
					{
						throw new AttrributeException(ERR_MSG_1002);
					}
				}
				else
				{
					m_intShapeType = (int)Shape.Type;
					m_objAttributesDefinition = Attributes;
						
					//switch(
					//update the bounding box for the first record, i.e. record each value for min and max
					UpdateBoundingBox(Shape, true);
				}

				//can only get here if both shape and attributes are OK
				m_colShapes.Add(Shape);
				m_colAttributeCollections.Add(Attributes);

				//update the bounding box
				UpdateBoundingBox(Shape, false);

			}
			catch(Exception e)
			{
				throw new ShapeException(e.Message, e);
			}
		}

		private void UpdateBoundingBox(ShapeBase objShape, bool blnInitialise)
		{
			// need to cast the object to its type first
			switch (objShape.Type)
			{
				case ShapeType.ShapeTypeNull:
						
					//set X, Y, M and Z

					break;

				case ShapeType.ShapeTypePoint:

					Point objPoint = (Point)objShape;
					
					//set X, Y, M and Z
					if(blnInitialise)
					{
						//max values same as min values
						m_dblXmin = objPoint.ValueX;
						m_dblYmin = objPoint.ValueY;
						m_dblXmax = objPoint.ValueX;
						m_dblYmax = objPoint.ValueY;
				
					}
					else
					{
						if(m_dblXmin > objPoint.ValueX) m_dblXmin = objPoint.ValueX;
						if(m_dblYmin > objPoint.ValueY) m_dblYmin = objPoint.ValueY;
						if(m_dblXmax < objPoint.ValueX) m_dblXmax = objPoint.ValueX;
						if(m_dblYmax < objPoint.ValueY) m_dblYmax = objPoint.ValueY;

					}

					break;

				case ShapeType.ShapeTypePolyLine:

					PolyLine objPolyline = (PolyLine)objShape;
					
					//set X, Y, M and Z
					if(blnInitialise)
					{
						m_dblXmin = objPolyline.MinValueX;
						m_dblYmin = objPolyline.MinValueY;
						m_dblXmax = objPolyline.MaxValueX;
						m_dblYmax = objPolyline.MaxValueY;
				
					}
					else
					{
						if(m_dblXmin > objPolyline.MinValueX) m_dblXmin = objPolyline.MinValueX;
						if(m_dblYmin > objPolyline.MinValueY) m_dblYmin = objPolyline.MinValueY;
						if(m_dblXmax < objPolyline.MaxValueX) m_dblXmax = objPolyline.MaxValueX;
						if(m_dblYmax < objPolyline.MaxValueY) m_dblYmax = objPolyline.MaxValueY;

					}

					break;

				case ShapeType.ShapeTypePolygon:

					Polygon objPolygon = (Polygon)objShape;
					
					//set X, Y, M and Z
					if(blnInitialise)
					{
						m_dblXmin = objPolygon.MinValueX;
						m_dblYmin = objPolygon.MinValueY;
						m_dblXmax = objPolygon.MaxValueX;
						m_dblYmax = objPolygon.MaxValueY;
				
					}
					else
					{
						if(m_dblXmin > objPolygon.MinValueX) m_dblXmin = objPolygon.MinValueX;
						if(m_dblYmin > objPolygon.MinValueY) m_dblYmin = objPolygon.MinValueY;
						if(m_dblXmax < objPolygon.MaxValueX) m_dblXmax = objPolygon.MaxValueX;
						if(m_dblYmax < objPolygon.MaxValueY) m_dblYmax = objPolygon.MaxValueY;

					}

					break;

				case ShapeType.ShapeTypePointM:

					//set X, Y, M and Z
					if(blnInitialise)
					{

					}
					else
					{

					}
					break;

				case ShapeType.ShapeTypePolyLineM:

					//set X, Y, M and Z
					if(blnInitialise)
					{

					}
					else
					{

					}
					break;

				case ShapeType.ShapeTypePolygonM:
					
					//set X, Y, M and Z
					if(blnInitialise)
					{

					}
					else
					{

					}
					break;

				case ShapeType.ShapeTypePointZ:

					//set X, Y, M and Z
					if(blnInitialise)
					{

					}
					else
					{

					}
					break;

				case ShapeType.ShapeTypePolyLineZ:

					//set X, Y, M and Z
					if(blnInitialise)
					{

					}
					else
					{

					}
					break;

				case ShapeType.ShapeTypePolygonZ:
						
					//set X, Y, M and Z
					if(blnInitialise)
					{

					}
					else
					{

					}
					break;
			}

		}
		private bool CompareAttributes(Attributes Attributes1, Attributes Attributes2)
		{

			//need to compare the Name and type, values will be different
			//first check that they are both the same length
			if(Attributes1.Count == Attributes2.Count)
			{
				for(int f = 0;f < Attributes1.Count; f++)
				{
					if((Attributes1[f].Name != Attributes2[f].Name) || Attributes1[f].Type != Attributes2[f].Type)
					{
						return false;
					}
				}

			}
			else
			{
				return false;
			}

			return true;
		}
		private static string ByteToHex(byte[] ByteData)
		{
			//---------------------------------------------------------------------------
			//	DESCRIPTION:	This function converts an array of bytes to a string
			//					of hex digits representing those bytes.
			//
			//
			//	PARAMETERS:
			//				ByteData()  Array of bytes.
			//
			//	RETURNS:
			//				String      String of hex character pairs representing
			//							each byte in the byte array, separated
			//							with a space.
			//
			//---------------------------------------------------------------------------
		
			string sTemp = "";
			string sMessage = "";

				if(ByteData != null)
				{
					for(int f = 0;f <= ByteData.GetUpperBound(0);f++)
					{
						sTemp = ByteData[f].ToString("X"); //hex returns a string representing the passed number

						if(sTemp.Length < 2)
						{
							sTemp = string.Concat("0", sTemp);
						}
						
						sMessage = string.Concat(sMessage, " ", sTemp);
					}
					
					return sMessage.Trim();
				}
				else
				{
					return "";
				}
		}


		private static string ByteToAsc(byte[] ByteData)
		{
			//---------------------------------------------------------------------------
			//   DESCRIPTION:    This function converts an array of bytes to a string
			//                   of ascii characters representing those bytes.
			//
			//
			//   PARAMETERS:
			//                   ByteData()  Array of bytes.
			//
			//   RETURNS:
			//                   String      String of ascii character representing
			//                               each byte in the byte array, an invalid
			//                               ascii code is represented by a ".".
			//
			//---------------------------------------------------------------------------

			char chrTemp = '.';
			string sMessage = "";

				if(ByteData != null)
				{
					for(int f = 0;f <= ByteData.GetUpperBound(0);f++)
					{
						if((ByteData[f] >= 32) && (ByteData[f] <= 127))
						{
                            chrTemp = System.Convert.ToChar(ByteData[f], CultureInfo.InvariantCulture);
						}
						else
						{
							chrTemp = '.';
						}
		
						sMessage = string.Concat(sMessage,chrTemp.ToString(CultureInfo.InvariantCulture));

					}
				}			
			
			return sMessage.Trim();

		}

		public int FileCode
		{
			get
			{
				return m_intFileCode;
			}
		}

		public int Version
		{
			get
			{
				return m_intVersion;

			}
		}

		public int FileLength
		{
			get
			{
				return m_intFileLength;
			}
		}

//		public int Unused1
//		{
//			get
//			{
//				return m_intUnused1;
//			}
//		}
//
//		public int Unused2
//		{
//			get
//			{
//				return m_intUnused2;
//			}
//		}
//
//		public int Unused3
//		{
//			get
//			{
//				return m_intUnused3;
//			}
//		}
//
//		public int Unused4
//		{
//			get
//			{
//				return m_intUnused4;
//			}
//		}
//
//		public int Unused5
//		{
//			get
//			{
//				return m_intUnused5;
//			}
//		}
	}
}
